import argparse

from pymongo import MongoClient
import time
import copy
import csv
import concurrent.futures
from threading import Lock
import os


def main():
    # 初始化输出文件夹
    if not os.path.exists("./output"):
        os.mkdir("./output")
    parser = argparse.ArgumentParser(description="输入数据库地址")

    parser.add_argument('--db', type=str, default=None,
                        help='数据库地址 例如: mongodb://127.0.0.1:27017')
    parser.add_argument('--taskType', nargs='+', type=str, default=None,
                        help='导出的任务类型（逗号分隔，例如: 类型1,类型2')

    args = parser.parse_args()
    # 这里替换成一下mongodb连接参数
    uri = args.db
    task_type_names = args.taskType
    print(uri, task_type_names)
    client = MongoClient(uri)
    db = client['lesschat']

    task_states = db['mission_task_states'].find()
    task_props = db['mission_task_props'].find()
    task_props_copy = copy.copy(task_props)
    task_props_name = dict(
        [(str(task_prop['key']), task_prop['name']) for task_prop in task_props])
    task_props_type = dict(
        [(str(task_prop['key']), task_prop['type']) for task_prop in task_props_copy])
    # 将task_states中的_id 和 name 组成字典 _id为key name为value
    task_state_ids = dict(
        [(str(task_state['_id']), task_state['name']) for task_state in task_states])

    task_type_ids = db['mission_task_types'].find(
        {'name': {'$in': task_type_names}, 'is_deleted': {'$ne': 1}}, {'_id': 1, 'name': 1, 'properties': 1})
    task_type_properties = copy.copy(task_type_ids)
    task_type_properties = dict([(str(task_type_propertie['_id']), task_type_propertie['properties'])
                                 for task_type_propertie in task_type_properties])

    task_type_ids = dict([(task_type_id['name'], task_type_id['_id'])
                         for task_type_id in task_type_ids])

    for task_type_name in task_type_names:
        # 获取总数
        data_count = db['mission_tasks'].count_documents(
            {'task_type_id': task_type_ids[task_type_name], 'is_deleted': {'$ne': 1}}) if 'count_documents' in dir(db['mission_tasks']) else db['mission_tasks'].count()
        print(task_type_name, data_count)
        data_infos = db['mission_tasks'].find({'task_type_id': task_type_ids[task_type_name], 'is_deleted': {'$ne': 1}}, {
            '_id': 1, 'created_at': 1, 'updated_at': 1, 'title': 1, 'properties': 1, 'task_type_id': 1, 'task_state_id': 1})
        all_data = []
        keys = set({'_id', '创建时间', '修改时间', '任务名称', '任务类型', '任务状态'})  # 初始化为集合
        keys_lock = Lock()  # 字段锁
        data_lock = Lock()  # 数据锁

        # 将游标转换为列表以支持多线程处理
        data_infos = list(data_infos)

        with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
            futures = []
            for data_info in data_infos:
                future = executor.submit(
                    process_data_info,
                    data_info=data_info,
                    task_type_name=task_type_name,
                    task_props_name=task_props_name,
                    task_props_type=task_props_type,
                    task_type_properties=task_type_properties,
                    task_state_ids=task_state_ids,
                    db=db
                )
                futures.append(future)

            for future in concurrent.futures.as_completed(futures):
                try:
                    data_dict, dynamic_keys = future.result()
                    with keys_lock:
                        keys.update(dynamic_keys)
                    with data_lock:
                        all_data.append(data_dict)
                except Exception as e:
                    print(f"处理数据时发生错误: {str(e)}")

        if all_data:
            keys = list(keys)
            # print(keys)
            with open(f'./output/{task_type_name}.csv', 'w', encoding='utf-8-sig') as f:
                writer = csv.DictWriter(f, fieldnames=keys)
                writer.writeheader()
                writer.writerows(all_data)
                print(f"{task_type_name}导出成功")
                print(os.path.abspath(f'./output/{task_type_name}.csv'))


# 时间戳转换
def timestamp_to_time(timestamp):
    time_local = time.localtime(timestamp)
    dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
    return dt


# 根据prop_type获取value,pr
def get_value(db, prop_type, value, _id):
    prop_type = str(prop_type)
    try:
        if not value:
            return ''
        if 'value' not in value:
            return ''
        v_value = value['value']
        if v_value is None:
            return ''
        if prop_type == '4':
            return timestamp_to_time(v_value['date'])
        if prop_type == '5':
            return f'{timestamp_to_time(v_value["begin"]["date"])}~{timestamp_to_time(v_value["end"]["date"])}'
        if prop_type == '6':
            if 'property_attribute' in value and value['property_attribute'] and 'is_reference' in value['property_attribute'] and value['property_attribute']['is_reference'] and value['property_attribute']['is_reference'] == 0:
                return find(value['property_attribute']['items'], lambda x: str(x['_id']) == str(v_value))['text']
            else:
                # 判断v_value是否为字符串类型，如果是，则直接返回v_value
                if isinstance(v_value, str):
                    return v_value
                return db['mission_task_data_source_items'].find_one(
                    {'_id': v_value})['text']

        if prop_type == '9':
            return db['users'].find_one({'uid': v_value})['display_name']

        if prop_type == '10':
            users = db['users'].find({'uid': {'$in': v_value}})
            user_names = [user['display_name'] for user in users]
            if user_names:
                return ','.join(user_names)
        if prop_type == '22':
            list_values = []
            if 'property_attribute' in value and value['property_attribute'] and 'is_reference' in value['property_attribute'] and value['property_attribute']['is_reference'] and value['property_attribute']['is_reference'] == 0:
                for v in v_value:
                    t = find(value['property_attribute']['items'], lambda x: str(
                        x['_id']) == str(v))['text']
                    list_values.append(t)
                return ','.join(list_values)
            else:
                v_datas = db['mission_task_data_source_items'].find(
                    {'_id': {'$in': v_value}})
                if v_datas:
                    return ','.join([v_data['text'] for v_data in v_datas])
        if prop_type == '28':
            return ','.join([v['title'] for v in v_value])
        if prop_type == '30':
            return v_value['text']
        else:
            return v_value
    except Exception as e:
        with open('error.txt', 'a', encoding='utf-8') as f:
            f.write(
                f"处理数据时发生错误: {str(e)},_id:{_id},prop_type:{prop_type},valeue:{value}\n")
        print(
            f"处理数据时发生错误: {str(e)},_id:{_id},prop_type:{prop_type},valeue:{value}")
        return ''


def find(lst, predicate):
    for item in lst:
        if predicate(item):
            return item
    return None


def process_data_info(data_info, task_type_name, task_props_name, task_props_type,
                      task_type_properties, task_state_ids, db):
    data_dict = {}
    dynamic_keys = set()  # 用于收集当前数据新增的字段

    # 固定字段处理
    data_dict['_id'] = str(data_info['_id'])
    data_dict['创建时间'] = timestamp_to_time(data_info['created_at'])
    data_dict['修改时间'] = timestamp_to_time(data_info['updated_at'])
    data_dict['任务名称'] = data_info['title']
    data_dict['任务类型'] = task_type_name
    data_dict['任务状态'] = task_state_ids[str(data_info['task_state_id'])]

    # 动态属性字段处理
    for key, value in data_info['properties'].items():
        name = task_props_name.get(key, '')
        dynamic_keys.add(name)  # 记录动态字段

        props_type = task_props_type.get(key, '')
        task_type_propertie = task_type_properties.get(
            str(data_info['task_type_id']), []
        )

        # 属性配置查找
        v = find(task_type_propertie,
                 lambda x: str(x.get('property_id', '')) == str(value.get('property_id', '')))
        if v:
            value['property_attribute'] = v.get('property_attribute', {})

        # 获取字段值
        data_dict[name] = get_value(db, props_type, value, data_dict['_id'])

    return data_dict, dynamic_keys


if __name__ == '__main__':
    main()
